#ifndef PW_PBL_ALLOCATOR_HPP
#define PW_PBL_ALLOCATOR_HPP

#include <concepts>
#include <new>
#include <algorithm>

namespace pw_pbl
{
	template <typename T>
	concept ccAllocator = requires(T &allocator) {
		{
			allocator.allocate(size_t(12), size_t(4))
		} -> std::convertible_to<void *>;
		{
			allocator.realloc((void *)nullptr, size_t(12), size_t(4))
		} -> std::convertible_to<void *>;
		allocator.deallocate((void *)nullptr);
	};
} // namespace pw_pbl

#if __has_include("config/pw_pbl/Allocator.hpp")
#	include "config/pw_pbl/Allocator.hpp"
#elif __has_include("config/pw_pbl/config.hpp")
#	include "config/pw_pbl/config.hpp"
#else
#	include "default-config/Allocator.hpp"
#endif

namespace pw_pbl
{
	/// 分配器
	/// @tparam ...T 分配器参数
	template <typename... T>
	using Allocator = config::Allocator<T...>;

	/// 标准库兼容分配器
	/// @tparam T 元素类型
	/// @tparam ...P 分配器参数
	template <typename T, typename... P>
	struct StdAllocator
	{
		using value_type = T;
		using size_type = size_t;
		using difference_type = ptrdiff_t;
		using is_always_equal = std::true_type;

		[[nodiscard]] constexpr T *allocate(std::size_t n) { return Allocator<P...>::allocate(sizeof(T) * n, alignof(T)); }
		constexpr void deallocate(T *p, std::size_t) { Allocator<P...>::deallocate(p); }
	};
} // namespace pw_pbl

#endif // PW_PBL_ALLOCATOR_HPP
